package com.xuhuan.thread.study2.productiveconsumption;

/**
 * @author huan.xu
 * @date 2021/9/30 9:50
 * @description 生产者消费者问题：利用管程法解决
 * 需要对象：生产者、消费者、商品、缓冲区
 */
public class ProductiveConsumptionDemo1 {
    public static void main(String[] args) {
        BufferZone bufferZone = new BufferZone(5);

        new Productor(bufferZone, 20).start();
        new Consumer(bufferZone, 20).start();
    }
}

/**
 * 生产者
 */
class Productor extends Thread {

    /**
     * 总共生产多少
     */
    private int num;

    private BufferZone bufferZone;

    public Productor(BufferZone bufferZone, int num) {
        this.bufferZone = bufferZone;
        this.num = num;
    }

    @Override
    public void run() {
        for (int i = 1; i <= this.num; i++) {
            bufferZone.push(new Cola("可乐" + i));
        }

    }
}

/**
 * 消费者
 */
class Consumer extends Thread {

    /**
     * 总共生产多少
     */
    private int num;

    private BufferZone bufferZone;

    public Consumer(BufferZone bufferZone, int num) {
        this.bufferZone = bufferZone;
        this.num = num;
    }

    @Override
    public void run() {
        for (int i = 1; i <= this.num; i++) {
            System.out.println("--------------");
            System.out.println("当前缓冲区还有" + this.bufferZone.getCount() + "瓶可乐");
            Cola cola = this.bufferZone.pop();
            System.out.println("消费者消费了一瓶可乐[" + cola.getName() + "]");

        }

    }
}

/**
 * 缓冲区
 */
class BufferZone {

    /**
     * 缓冲区大小
     */
    private int max;

    /**
     * 缓冲区
     */
    private Cola[] colas;
    /**
     * 计数器
     */
    private int count = 0;

    public BufferZone(int maxNum) {
        this.max = maxNum;
        this.colas = new Cola[maxNum];
    }

    /**
     * 生产组把可乐放入缓存区
     *
     * @param cola
     */
    public synchronized void push(Cola cola) {
        //如果缓冲区满了，就需要等待消费者消费
        if (count >= this.max) {
            //通知消费者消费，生产者等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        //如果没有满，就需要等生产者生产可乐
        colas[count] = cola;
        count++;

        //通知消费者消费
        this.notifyAll();

    }

    /**
     * 消费者取出可乐
     *
     * @return
     */
    public synchronized Cola pop() {
        System.out.println("pop count[" + count + "]");
        //判断是否能够消费
        if (count <= 0) {
            //等待生产者生产，消费者等待
            try {
                this.wait();
                System.out.println("购买不成功");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费
        count--;
        Cola cola = this.colas[count];

        this.notifyAll();
        return cola;
    }

    /**
     * 获取缓冲区还有多少可乐
     *
     * @return
     */
    public int getCount() {
        return this.count;
    }

    /**
     * 获取缓冲区的可乐
     *
     * @return
     */
    private String getBufferColas() {
        return colas.toString();
    }

}

/**
 * 商品：可乐
 */
class Cola {
    private String name;

    public Cola(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}